﻿using UnityEngine;
using System.Collections;
using Assets.Engine.AI.FiniteStateMachine;
using Assets.Engine.AI.FiniteStateMachine.States;
using Assets.Engine.SimpleArrow;
using Engine.Entities.Character;
using Game.Scripts.Managers;
using FloodFill;

[RequireComponent(typeof(Boid))]
[RequireComponent(typeof(StevePathfindedController))]
public class SteveBrain : MonoBehaviour {

    
    private SteveModel data;
    private PartyController partyController;
    private Building building;
    private bool isHavingFun;
    private bool isStatusChanged;

    void Awake() {
        this.isStatusChanged = true;
        this.model = new SteveModel(GenderEnum.Undefined);
        this.havingFun = false;
    }

    void Update() {
        if (this.isStatusChanged) {

            //has a party?
            if (this.isPartyMember) {
                //the party is having fun?
                if (this.havingFun) {
                    //follow the swarm
                    this.startHavingFun();
                } else {
                    //continue on doing his duty
                    this.doOrdinaryActivity();
                }
            } else {
                //continue on doing his duty
                this.doOrdinaryActivity();
            }

            this.isStatusChanged = false;
        }
    }

    private void doOrdinaryActivity() {
        Boid boid = this.GetComponent<Boid>();        
        StevePathfindedController mover = this.GetComponent<StevePathfindedController>();
        Vector3 targetPlace = Vector3.zero;
        EventDelegate onDestinationReached = null;

        boid.stopReacting();
        if(this.isWorker){
            //working character, just goes back to his workplace.
            targetPlace = this.workplace.transform.position;
            onDestinationReached = new EventDelegate(this, "onWorkPlaceReached");
        } else {
            //idle character. just hangs around the map randomly.

            //chiedo al floodfill una posizione casuale vuota nell'isola
            FrenzyIslandGenerator island = FrenzyPeopleController.instance.GetComponent<FrenzyIslandGenerator>();
            Voxel v = null;
            do
            {
                Node n = island.scannerField.FloodResult.GetRandomNodeVisited();
                targetPlace = new Vector3(n.x, 0, n.z);
                v = island.getTopVoxelAt(n.x, n.z);
            } while (v.content.informativeContent != null);
            
            //targetPlace = new Vector3(Random.Range(30, 90), 0, Random.Range(30, 90));

            onDestinationReached = new EventDelegate(this, "onHangingRandomPlaceReached");
        }
        mover.SetTarget(targetPlace, onDestinationReached);
    }


    private void startHavingFun() {
        Boid boid = this.GetComponent<Boid>();
        StevePathfindedController mover = this.GetComponent<StevePathfindedController>();

        mover.Stop();
        if (this.isPartyMember) {
            //character with a party, follow swarm (act as a boid).
            boid.startReacting();
        }
    }


    /// <summary>
    /// Implementare qui dentro la logica applicativa
    /// per quando un agente raggiunge il proprio posto di lavoro
    /// </summary>
    private void onWorkPlaceReached() {
        
    }


    /// <summary>
    /// Una volta che l'agente raggiunge un punto casuale
    /// quando non ha lavoro (e non in modalità divertimento)
    /// allora il suo stato non è cambiato, sfrutto
    /// la logica dell'Update per generare una nuova destinazione
    /// casuale.
    /// </summary>
    private void onHangingRandomPlaceReached() {
        this.isStatusChanged = true;
    }



    public bool isWorker {
        get {
            return this.workplace != null;
        }
    }

    public bool isPartyMember {
        get {
            return this.partyController != null;
        }
    }

    public bool havingFun {
        get {
            return this.isHavingFun;
        }

        set {
            this.isHavingFun = value;
            this.isStatusChanged = true;
        }
    }

    public SteveModel model {
        get {
            return this.data;
        }

        set {
            this.data = value;
        }
    }

    public PartyController party {
        get {
            return this.partyController;
        }

        set {
            this.partyController = value;
            this.isStatusChanged = true;
        }
    }

    public Building workplace {
        get {
            return this.building;
        }

        set {
            this.building = value;
            this.isStatusChanged = true;
        }
    }
    
}
